namespace SimpleWebServices.Configuration
{
    using System;
    using System.Xml;
    using System.Xml.XPath;
    using Xunit;

    public sealed class DefaultFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<Default>()
                .DerivesFrom<object>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new Default());
        }

        [Fact]
        public void prop_Objects_get()
        {
            Assert.NotNull(new Default().Objects);
        }

        [Fact]
        public void op_Clear()
        {
            try
            {
                int expected = 0;
                int actual = 1;

                actual = new Default().Objects.Count;
                Assert.NotEqual<int>(expected, actual);

                Default.Clear();
                actual = new Default().Objects.Count;
                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_string()
        {
            Default.Clear();

            try
            {
                Default.Register<DefaultTest>("<test />");

                int expected = 1;
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_stringEmpty()
        {
            Assert.Throws<ArgumentOutOfRangeException>(() => Default.Register<DefaultTest>(string.Empty));
        }

        [Fact]
        public void op_Register_stringInvalid()
        {
            Assert.Throws<XmlException>(() => Default.Register<DefaultTest>("invalid"));
        }

        [Fact]
        public void op_Register_stringNull()
        {
            Assert.Throws<ArgumentNullException>(() => Default.Register<DefaultTest>(null as string));
        }

        [Fact]
        public void op_Register_string_string()
        {
            Default.Clear();

            try
            {
                Default.Register<DefaultTest>("name", "<test />");

                int expected = 1;
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_stringEmpty_string()
        {
            Default.Clear();

            try
            {
                Default.Register<DefaultTest>(string.Empty, "<test />");

                int expected = 1;
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_stringNull_string()
        {
            Default.Clear();

            try
            {
                int expected = 1;

                Default.Register<DefaultTest>(null as string, "<test />");
                
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_IXPathNavigable()
        {
            Default.Clear();

            try
            {
                XmlDocument xml = new XmlDocument();
                xml.LoadXml("<test />");

                Default.Register<DefaultTest>(xml as IXPathNavigable);

                int expected = 1;
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_IXPathNavigableNull()
        {
            Assert.Throws<ArgumentNullException>(() => Default.Register<DefaultTest>(null as IXPathNavigable));
        }

        [Fact]
        public void op_Register_string_IXPathNavigable()
        {
            Default.Clear();

            try
            {
                XmlDocument xml = new XmlDocument();
                xml.LoadXml("<test />");

                Default.Register<DefaultTest>("name", xml as IXPathNavigable);

                int expected = 1;
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_stringEmpty_IXPathNavigable()
        {
            Default.Clear();

            try
            {
                XmlDocument xml = new XmlDocument();
                xml.LoadXml("<test />");

                Default.Register<DefaultTest>(string.Empty, xml as IXPathNavigable);

                int expected = 1;
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_stringNull_IXPathNavigable()
        {
            Default.Clear();

            try
            {
                XmlDocument xml = new XmlDocument();
                xml.LoadXml("<test />");

                Default.Register<DefaultTest>(null as string, xml as IXPathNavigable);

                int expected = 1;
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_Register_string_IXPathNavigableNull()
        {
            Assert.Throws<ArgumentNullException>(() => Default.Register<DefaultTest>("name", null as IXPathNavigable));
        }

        [Fact]
        public void op_Reset()
        {
            try
            {
                int expected = new Default().Objects.Count;

                Default.Clear();

                Default.Register<DefaultTest>("test 1", "<test />");
                Default.Register<DefaultTest>("test 2", "<test />");

                Default.Reset();
                int actual = new Default().Objects.Count;

                Assert.Equal<int>(expected, actual);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_ObjectOfT()
        {
            try
            {
                Default.Register<DefaultTest>("<test value='example'/>");

                DefaultTest actual = new Default().Object<DefaultTest>();

                Assert.Equal<string>("example", actual.Value);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_ObjectOfT_whenDefaultClass()
        {
            Assert.Null(new Default().Object<Uri>());
        }

        [Fact]
        public void op_ObjectOfT_whenDefaultStruct()
        {
            DateTime expected = new DateTime();
            DateTime actual = new Default().Object<DateTime>();

            Assert.Equal<DateTime>(expected, actual);
        }

        [Fact]
        public void op_ObjectOfT_string()
        {
            try
            {
                Default.Register<DefaultTest>("release", "<test value='example'/>");

                DefaultTest actual = new Default().Object<DefaultTest>("release");

                Assert.Equal<string>("example", actual.Value);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_ObjectOfT_string_whenDefaultClass()
        {
            Assert.Null(new Default().Object<Uri>("unknown"));
        }

        [Fact]
        public void op_ObjectOfT_string_whenDefaultStruct()
        {
            DateTime expected = new DateTime();
            DateTime actual = new Default().Object<DateTime>("unknown");

            Assert.Equal<DateTime>(expected, actual);
        }

        [Fact]
        public void op_ObjectOfT_stringEmpty()
        {
            try
            {
                Default.Register<DefaultTest>("<test value='example'/>");

                DefaultTest actual = new Default().Object<DefaultTest>(string.Empty);

                Assert.Equal<string>("example", actual.Value);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_ObjectOfT_stringEmpty_whenDefaultClass()
        {
            try
            {
                Default.Register<DefaultTest>("<test value='example'/>");

                Assert.NotNull(new Default().Object<DefaultTest>(string.Empty));
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_ObjectOfT_stringEmpty_whenDefaultStruct()
        {
            DateTime expected = new DateTime();
            DateTime actual = new Default().Object<DateTime>(string.Empty);

            Assert.Equal<DateTime>(expected, actual);
        }

        [Fact]
        public void op_ObjectOfT_stringNull()
        {
            try
            {
                Default.Register<DefaultTest>("<test value='example'/>");

                DefaultTest actual = new Default().Object<DefaultTest>(null);

                Assert.Equal<string>("example", actual.Value);
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_ObjectOfT_stringNull_whenDefaultClass()
        {
            try
            {
                Default.Register<DefaultTest>("<test value='example'/>");

                Assert.NotNull(new Default().Object<DefaultTest>(null));
            }
            finally
            {
                Default.Reset();
            }
        }

        [Fact]
        public void op_ObjectOfT_stringNull_whenDefaultStruct()
        {
            DateTime expected = new DateTime();
            DateTime actual = new Default().Object<DateTime>(null);

            Assert.Equal<DateTime>(expected, actual);
        }
    }
}